home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / dvips.new / output.c < prev    next >
C/C++ Source or Header  |  1990-12-17  |  14KB  |  616 lines

  1. /*
  2.  *   These routines do most of the communicating with the printer.
  3.  *
  4.  *   LINELENGTH tells the maximum line length to send out.
  5.  */
  6. #define LINELENGTH (78)
  7. #include "structures.h" /* The copyright notice in that file is included too! */
  8. #include <ctype.h>
  9. /*
  10.  *   The external routines called here:
  11.  */
  12. extern void error() ;
  13. extern void send_headers() ;
  14. extern FILE *search() ;
  15. extern char *getenv() ;
  16. extern void fonttableout() ;
  17. extern void makepsname() ;
  18. /*
  19.  *   These are the external variables used by these routines.
  20.  */
  21. extern integer hh, vv ;
  22. extern fontdesctype *curfnt ;
  23. extern FILE *bitfile ;
  24. extern char *oname ;
  25. extern Boolean reverse ;
  26. extern Boolean removecomments ;
  27. extern Boolean sendcontrolD, disablecomments, multiplesects ;
  28. extern Boolean usesPSfonts, headers_off ;
  29. extern Boolean safetyenclose ;
  30. extern int numcopies ;
  31. extern int totalpages ;
  32. extern integer pagenum ;
  33. extern Boolean manualfeed ;
  34. extern int landscape ;
  35. extern int quiet ;
  36. extern int prettycolumn ;
  37. extern int actualdpi ;
  38. extern char *iname ;
  39. extern char *paperfmt ;
  40. extern char *headerpath ;
  41. extern char errbuf[] ;
  42. extern shalfword linepos ;
  43. extern char *figpath ;
  44. extern struct header_list *ps_fonts_used ;
  45. extern char banner[] ;
  46. /*
  47.  *   We need a few statics to take care of things.
  48.  */
  49. static integer rhh, rvv ;
  50. static int instring ;
  51. static Boolean lastspecial = 1 ;
  52. static shalfword d ;
  53. static Boolean popened = 0 ;
  54. int lastfont ; /* exported to dospecial to fix rotate.tex problem */
  55. static void chrcmd();                   /* just a forward declaration */
  56. static char strbuffer[LINELENGTH + 20], *strbp = strbuffer ;
  57. static struct {
  58.     char *format;
  59.     int width, height;
  60. } paper_types[] = {
  61.     { "letter",  612,  792 },        /* 8.5 x 11 */
  62.     { "legal",   612, 1008 },        /* 8.5 x 14 */
  63.     { "ledger",  792, 1224 },        /* 11 x 17 */
  64.     { "a4",     596,  843 },        /* 210mm x 297mm */
  65.     { "a3",      843, 1192 } };        /* 297mm x 420mm */
  66. /*
  67.  *   This routine copies a file down the pipe.  Search path uses the
  68.  *   header path.
  69.  */
  70. static int infigure ;
  71. void
  72. copyfile(s)
  73.         char *s ;
  74. {
  75.    FILE *f ;
  76.    int c, prevc = '\n' ;
  77.  
  78.    switch (infigure) {
  79.    case 1:
  80.       f = search(figpath, s, READ) ;
  81.       (void)sprintf(errbuf, "Couldn't find figure file %s; continuing", s) ;
  82.       break ;
  83.    default:
  84.       f = search(headerpath, s, READ) ;
  85.       (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  86.       break ;
  87. #ifndef VMS
  88. #ifndef MSDOS
  89.    case 2:
  90.       f = popen(s, "r") ;
  91.       (void)sprintf(errbuf, "Failure to execute %s; continuing", s) ;
  92.       break;
  93. #endif
  94. #endif
  95.    }
  96.    if (f==NULL)
  97.       error(errbuf) ;
  98.    else {
  99.       if (! quiet) {
  100.          if (strlen(s) + prettycolumn > 76) {
  101.             fprintf(stderr, "\n") ;
  102.             prettycolumn = 0 ;
  103.          }
  104.          (void)fprintf(stderr, "<%s>", s) ;
  105.          (void)fflush(stderr) ;
  106.          prettycolumn += 2 + strlen(s) ;
  107.       }
  108.       if (linepos != 0)
  109.          (void)putc('\n', bitfile) ;
  110.       if (! disablecomments)
  111.          if (infigure)
  112.             (void)fprintf(bitfile, "%%%%BeginDocument: %s\n", s) ;
  113.          else
  114.             (void)fprintf(bitfile, "%%%%BeginProcSet: %s\n", s) ;
  115.       while ((c=getc(f))!=EOF && c != 4) {
  116.          if (! removecomments && c == '%' && prevc == '\n') {/* skip comments */
  117.             while ((c=getc(f))!=EOF) {
  118.                if (c=='\n')
  119.                   break ;
  120.             }
  121.          } else
  122.             (void)putc(c, bitfile) ;
  123.          prevc = c ;
  124.       }
  125.       if (prevc != '\n')
  126.          (void)putc('\n', bitfile) ;
  127.       linepos = 0 ;
  128. #ifndef VMS
  129. #ifndef MSDOS
  130.       if (infigure == 2)
  131.          (void)pclose(f) ;
  132.       else
  133. #endif
  134. #endif
  135.          (void)fclose(f) ;
  136.       if (!disablecomments)
  137.          if (infigure)
  138.             (void)fprintf(bitfile, "%%%%EndDocument\n") ;
  139.          else
  140.             (void)fprintf(bitfile, "%%%%EndProcSet\n") ;
  141.    }
  142. }
  143.  
  144. /*
  145.  *   For included PostScript graphics, we use the above routine, but
  146.  *   with no fatal error message.
  147.  */
  148. void figcopyfile(s, systemtype)
  149. char *s ;
  150. int systemtype ;
  151. {
  152.    infigure = systemtype ? 2 : 1 ;
  153.    copyfile(s) ;
  154.    infigure = 0 ;
  155. }
  156.  
  157. /*
  158.  *   This next routine writes out a `special' character.  In this case,
  159.  *   we simply put it out, since any special character terminates the
  160.  *   preceding token.
  161.  */
  162. void
  163. specialout(c)
  164.         char c ;
  165. {
  166.    if (linepos >= LINELENGTH) {
  167.       (void)putc('\n', bitfile) ;
  168.       linepos = 0 ;
  169.    }
  170.    (void)putc(c, bitfile) ;
  171.    linepos++ ;
  172.    lastspecial = 1 ;
  173. }
  174.  
  175. void
  176. stringend()
  177. {
  178.    if (linepos + instring >= LINELENGTH - 2) {
  179.       (void)putc('\n', bitfile) ;
  180.       linepos = 0 ;
  181.    }
  182.    (void)putc('(', bitfile) ;
  183.    *strbp = 0 ;
  184.    (void)fputs(strbuffer, bitfile) ;
  185.    (void)putc(')', bitfile) ;
  186.    linepos += instring + 2 ;
  187.    lastspecial = 1 ;
  188.    instring = 0 ;
  189.    strbp = strbuffer ;
  190. }
  191.  
  192. void
  193. scout(c)   /* string character out */
  194.         char c ;
  195. {
  196. /*
  197.  *   Is there room in the buffer?  LINELENGTH-6 is used because we
  198.  *   need room for (, ), and a possible four-byte string \000, for
  199.  *   instance.  If it is too long, we send out the string.
  200.  */
  201.    if (instring > LINELENGTH-6) {
  202.       stringend() ;
  203.       chrcmd('p') ;
  204.    }
  205.    if (c<' ' || c>126 || c=='%') {
  206.       *strbp++ = '\\' ;
  207.       *strbp++ = '0' + ((c >> 6) & 3) ;
  208.       *strbp++ = '0' + ((c >> 3) & 7) ;
  209.       *strbp++ = '0' + (c & 7) ;
  210.       instring += 4 ;
  211.    } else if (c == '(' || c == ')' || c == '\\') {
  212.       *strbp++ = '\\' ;
  213.       *strbp++ = c ;
  214.       instring += 2 ;
  215.    } else {
  216.       *strbp++ = c ;
  217.       instring++ ;
  218.    }
  219. }
  220.  
  221. void
  222. cmdout(s)
  223.         char *s ;
  224. {
  225.    int l ;
  226.  
  227.    /* hack added by dorab */
  228.    if (instring) {
  229.         stringend();
  230.         chrcmd('p');
  231.    }
  232.    l = strlen(s) ;
  233.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  234.            linepos + l >= LINELENGTH) {
  235.       (void)putc('\n', bitfile) ;
  236.       linepos = 0 ;
  237.       lastspecial = 1 ;
  238.    } else if (! lastspecial) {
  239.       (void)putc(' ', bitfile) ;
  240.       linepos++ ;
  241.    }
  242.    (void)fputs(s, bitfile) ;
  243.    linepos += l ;
  244.    lastspecial = 0 ;
  245. }
  246.  
  247.  
  248. static void
  249. chrcmd(c)
  250.         char c ;
  251. {
  252.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  253.        linepos + 2 > LINELENGTH) {
  254.       (void)putc('\n', bitfile) ;
  255.       linepos = 0 ;
  256.       lastspecial = 1 ;
  257.    } else if (! lastspecial) {
  258.       (void)putc(' ', bitfile) ;
  259.       linepos++ ;
  260.    }
  261.    (void)putc(c, bitfile) ;
  262.    linepos++ ;
  263.    lastspecial = 0 ;
  264. }
  265.  
  266. void
  267. floatout(n)
  268.         float n ;
  269. {
  270.    char buf[20] ;
  271.  
  272.    (void)sprintf(buf, "%.2f", n) ;
  273.    cmdout(buf) ;
  274. }
  275.  
  276. void
  277. numout(n)
  278.         integer n ;
  279. {
  280.    char buf[10] ;
  281.  
  282.    (void)sprintf(buf, "%ld", n) ;
  283.    cmdout(buf) ;
  284. }
  285.  
  286. void
  287. mhexout(p, len)
  288. register unsigned char *p ;
  289. register long len ;
  290. {
  291.    register char *hexchar = "0123456789ABCDEF" ;
  292.    register int n, k ;
  293.  
  294.    while (len > 0) {
  295.       if (linepos > LINELENGTH - 2) {
  296.          (void)putc('\n', bitfile) ;
  297.          linepos = 0 ;
  298.       }
  299.       k = (LINELENGTH - linepos) >> 1 ;
  300.       if (k > len)
  301.          k = len ;
  302.       len -= k ;
  303.       linepos += (k << 1) ;
  304.       while (k--) {
  305.          n = *p++ ;
  306.          (void)putc(hexchar[n >> 4], bitfile) ;
  307.          (void)putc(hexchar[n & 15], bitfile) ;
  308.       }
  309.    }
  310. }
  311.  
  312. void
  313. fontout(n)
  314.         int n ;
  315. {
  316.    char buf[6] ;
  317.  
  318.    if (instring) {
  319.       stringend() ;
  320.       chrcmd('p') ;
  321.    }
  322.    makepsname(buf, n) ;
  323.    cmdout(buf) ;
  324. }
  325.  
  326. void
  327. hvpos()
  328. {
  329.    if (rvv != vv) {
  330.       if (instring) {
  331.          stringend() ;
  332.          numout(hh) ;
  333.          numout(vv) ;
  334.          chrcmd('y') ;
  335.       } else if (rhh != hh) {
  336.          numout(hh) ;
  337.          numout(vv) ;
  338.          chrcmd('a') ;
  339.       } else { /* hard to get this case, but it's there when you need it! */
  340.          numout(vv - rvv) ;
  341.          chrcmd('x') ;
  342.       }
  343.       rvv = vv ;
  344.    } else if (rhh != hh) {
  345.       if (instring) {
  346.          stringend() ;
  347.          if (hh - rhh < 5 && rhh - hh < 5) {
  348.             chrcmd((char)('p' + hh - rhh)) ;
  349.          } else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
  350.             chrcmd((char)('g' + hh - rhh - d)) ;
  351.             d = hh - rhh ;
  352.          } else {
  353.             numout(hh - rhh) ;
  354.             chrcmd('b') ;
  355.             d = hh - rhh ;
  356.          }
  357.       } else {
  358.          numout(hh - rhh) ;
  359.          chrcmd('w') ;
  360.       }
  361.    }
  362.    rhh = hh ;
  363. }
  364.  
  365. /*
  366.  *   initprinter opens the bitfile and writes the initialization sequence
  367.  *   to it.
  368.  */
  369. void newline()
  370. {
  371.    if (linepos != 0) {
  372.       (void)fprintf(bitfile, "\n") ;
  373.       linepos = 0 ;
  374.    }
  375.    lastspecial = 1 ;
  376. }
  377.  
  378. void
  379. nlcmdout(s)
  380.         char *s ;
  381. {
  382.    newline() ;
  383.    cmdout(s) ;
  384.    newline() ;
  385. }
  386.  
  387. void
  388. initprinter()
  389. {
  390.    void tell_needed_fonts() ;
  391.    int i;
  392.    if (*oname != 0) {
  393. /*
  394.  *   We check to see if the first character is a exclamation
  395.  *   point, and popen if so.
  396.  */
  397.       if (*oname == '!' || *oname == '|') {
  398. #ifdef MSDOS
  399.             error("! can't open output pipe") ;
  400. #else
  401. #ifdef VMS
  402.             error("! can't open output pipe") ;
  403. #else
  404.          if ((bitfile=popen(oname+1, "w"))==NULL)
  405.             error("! couldn't open output pipe") ;
  406.          else
  407.             popened = 1 ;
  408. #endif
  409. #endif
  410.       } else {
  411.          if ((bitfile=fopen(oname,"w"))==NULL)
  412.             error("! couldn't open PostScript file") ;
  413.       }
  414.    } else {
  415.       bitfile = stdout ;
  416.    }
  417.    if (disablecomments)
  418.       (void)fprintf(bitfile,
  419.              "%%!PS (but not EPSF; comments have been disabled)\n") ;
  420.    else {
  421.       if (multiplesects)
  422.          (void)fprintf(bitfile,
  423.              "%%!PS (but not EPSF because of memory limits)\n") ;
  424.       else  (void)fprintf(bitfile, "%%!PS-Adobe-2.0\n") ;
  425.       (void)fprintf(bitfile, "%%%%Creator: %s", banner + 8) ;
  426.       if (*iname)
  427.          (void)fprintf(bitfile, "%%%%Title: %s\n", iname) ;
  428.       (void)fprintf(bitfile, "%%%%Pages: %d %d\n", totalpages, 1 - 2*reverse) ;
  429.       if (paperfmt && *paperfmt) {
  430.          for (i=0; i<sizeof(paper_types)/sizeof(paper_types[0]); ++i)
  431.             if (strcmp(paperfmt,paper_types[i].format)==0)
  432.                 (void)fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
  433.                     paper_types[i].width, paper_types[i].height) ;
  434.       } else
  435.          fprintf(bitfile, "%%%%BoundingBox: 0 0 612 792\n") ;
  436.       tell_needed_fonts() ;
  437.       (void)fprintf(bitfile, "%%%%EndComments\n") ;
  438.    }
  439.    if (safetyenclose)
  440.       (void)fprintf(bitfile, "/SafetyEnclosure save def\n") ;
  441.    if (! headers_off)
  442.       send_headers() ;
  443. }
  444.  
  445. static int endprologsent ;
  446. void setup() {
  447.    newline() ;
  448.    if (endprologsent == 0 && !disablecomments) {
  449.       fonttableout() ;
  450.       (void)fprintf(bitfile, "%%%%EndProlog\n") ;
  451.       (void)fprintf(bitfile, "%%%%BeginSetup\n") ;
  452.       (void)fprintf(bitfile, "%%%%Feature: *Resolution %d\n", DPI) ;
  453.       if (manualfeed)
  454.          (void)fprintf(bitfile, "%%%%Feature: *ManualFeed True\n") ;
  455.    }
  456.    cmdout("TeXDict") ;
  457.    cmdout("begin") ;
  458.    {
  459.       char pft[100] ;
  460.       strcpy(pft, "@") ;
  461.       if (landscape)
  462.          strcat(pft, "landscape ") ;
  463.       else if (paperfmt)
  464.          strcat(pft, paperfmt) ;
  465.       else
  466.          pft[0] = 0 ;
  467. /*    if (paperfmt) {         doing this has many bad effects!!!
  468.          strcat(pft, " /") ;
  469.          strcat(pft, paperfmt) ;
  470.          strcat(pft, " where {pop ") ;
  471.          strcat(pft, paperfmt) ;
  472.          strcat(pft, "} if") ;
  473.       } */
  474.       cmdout(pft) ;
  475.    }
  476.    if (manualfeed) cmdout("@manualfeed") ;
  477.    if (numcopies != 1) {
  478.       numout((integer)numcopies) ;
  479.       cmdout("@copies") ;
  480.    }
  481.    if (endprologsent == 0 && !disablecomments) {
  482.       newline() ;
  483.       endprologsent = 1 ;
  484.       (void)fprintf(bitfile, "%%%%EndSetup\n") ;
  485.    }
  486.  
  487. }
  488. /*
  489.  *   cleanprinter is the antithesis of the above routine.
  490.  */
  491. void
  492. cleanprinter()
  493. {
  494.    (void)fprintf(bitfile, "\n") ;
  495.    (void)fprintf(bitfile, "userdict /end-hook known{end-hook}if\n") ;
  496.    if (safetyenclose)
  497.       (void)fprintf(bitfile, "SafetyEnclosure restore\n") ;
  498.    if (!disablecomments)
  499.       (void)fprintf(bitfile, "%%%%EOF\n") ;
  500.    if (sendcontrolD)
  501.       (void)putc(4, bitfile) ;
  502. #ifndef MSDOS
  503. #ifndef VMS
  504.    if (popened)
  505.       (void)pclose(bitfile) ;
  506. #endif
  507. #endif
  508.    if (popened == 0)
  509.       (void)fclose(bitfile) ;
  510.    bitfile = NULL ;
  511. }
  512.  
  513. /* this tells dvips that it has no clue where it is. */
  514. static int thispage = 0 ;
  515. static integer rulex, ruley ;
  516. void psflush() {
  517.    rulex = ruley = rhh = rvv = -314159265 ;
  518.    lastfont = -1 ;
  519. }
  520. /*
  521.  *   pageinit initializes the output variables.
  522.  */
  523. void
  524. pageinit()
  525. {
  526.    psflush() ;
  527.    newline() ;
  528.    if (!disablecomments && !multiplesects)
  529.       (void)fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, ++thispage) ;
  530.    linepos = 0 ;
  531.    cmdout("bop") ;
  532.    d = 0 ;
  533. }
  534.  
  535.  
  536.  
  537. /*
  538.  *   This routine ends a page.
  539.  */
  540. void
  541. pageend()
  542. {
  543.    if (instring) {
  544.       stringend() ;
  545.       chrcmd('p') ;
  546.    }
  547.    cmdout("eop") ;
  548. }
  549.  
  550. /*
  551.  *   drawrule draws a rule at the specified position.
  552.  *   It does nothing to save/restore the current position,
  553.  *   or even draw the current string.  (Rules are normally
  554.  *   set below the baseline anyway, so this saves us on
  555.  *   output size almost always.)
  556.  */
  557. void
  558. drawrule(rw, rh)
  559.         integer rw, rh ;
  560. {
  561.    numout((integer)hh) ;
  562.    numout((integer)vv) ;
  563.    if (rw == rulex && rh == ruley)
  564.       chrcmd('V') ;
  565.    else {
  566.       numout((integer)rw) ;
  567.       numout((integer)rh) ;
  568.       chrcmd('v') ;
  569.       rulex = rw ;
  570.       ruley = rh ;
  571.    }
  572. }
  573.  
  574. /*
  575.  *   drawchar draws a character at the specified position.
  576.  */
  577. void
  578. drawchar(c, cc)
  579.         chardesctype *c ;
  580.         int cc ;
  581. {
  582.    hvpos() ;
  583.    if (lastfont != curfnt->psname) {
  584.       fontout((int)curfnt->psname) ;
  585.       lastfont = curfnt->psname ;
  586.    }
  587.    scout(cc) ;
  588.    rhh = hh + c->pixelwidth ; /* rvv = rv */
  589. }
  590. /*
  591.  *   This routine sends out the document fonts comment.
  592.  */
  593. void tell_needed_fonts() {
  594.    struct header_list *hl = ps_fonts_used ;
  595.    char *q ;
  596.    int roomleft = -1 ;
  597.    extern char *get_name() ;
  598.  
  599.    if (hl == 0)
  600.       return ;
  601.    while (q=get_name(&hl)) {
  602.       if ((int)strlen(q) >= roomleft) {
  603.          if (roomleft != -1) {
  604.             fprintf(bitfile, "\n%%%%+") ;
  605.             roomleft = LINELENGTH - 3 ;
  606.          } else {
  607.             fprintf(bitfile, "%%%%DocumentFonts:") ;
  608.             roomleft = LINELENGTH - 16 ;
  609.          }
  610.       }
  611.       fprintf(bitfile, " %s", q) ;
  612.       roomleft -= strlen(q) + 1 ;
  613.    }
  614.    fprintf(bitfile, "\n") ;
  615. }
  616.